/*
 * Copyright 2011 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package fr.gaellalire.jzip.actions;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import javax.swing.SwingWorker;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;

/**
 *
 * @author Gael Lalire
 */
public abstract class AbstractCompressAction extends SwingWorker<Void, Void> {

    public abstract OutputStream getOutputStream() throws IOException;

    public abstract List<FutureEntry> getFutureEntries() throws IOException;

    @Override
    protected Void doInBackground() throws Exception {
        long totalSize = 0;
        long currentSize = 0;

        OutputStream outputStream = getOutputStream();

        List<FutureEntry> futureEntries = getFutureEntries();

        if (outputStream == null) {
            for (FutureEntry futureEntry : futureEntries) {
                futureEntry.getInputStream().close();
            }
            return null;
        }

        for (FutureEntry futureEntry : futureEntries) {
            long length = futureEntry.getLength();
            if (length != -1) {
                totalSize += length;
            }
        }

        ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(outputStream);
        try {
            for (FutureEntry futureEntry : futureEntries) {
                long length = futureEntry.getLength();

                ZipArchiveEntry zipEntry = new ZipArchiveEntry(futureEntry.getName());
                zipOutputStream.putArchiveEntry(zipEntry);
                if (length != 0) {
                    InputStream input = futureEntry.getInputStream();
                    try {
                        final byte[] buffer = new byte[8192];
                        int n = 0;
                        while (-1 != (n = input.read(buffer))) {
                            zipOutputStream.write(buffer, 0, n);
                            currentSize += n;
                            if (length == -1) {
                                totalSize += n;
                            }
                            zipOutputStream.flush();
                            int progress = (int) (100 * currentSize / totalSize);
                            setProgress(progress);
                        }
                    } finally {
                        input.close();
                    }
                }
                zipOutputStream.closeArchiveEntry();
            }
        } finally {
            zipOutputStream.close();
        }

        setProgress(100);

        return null;
    }
}
